package com.liu.goods.controller;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.liu.goods.entity.GoodsEntity;
import com.liu.goods.entity.GoodsPngEntity;
import com.liu.goods.service.GoodsPngService;
import com.liu.goods.service.GoodsService;
import com.liu.goods.service.StockService;
import com.liu.goods.vo.GoodsAddVo;
import com.liu.shop.common.constant.ShopGoodsConstants;
import com.liu.shop.common.utils.PageUtils;
import com.liu.shop.common.utils.R;
import com.liu.shop.common.vo.GoodsVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;


/**
 * 
 *
 * @author lls
 * @email 302140431@qq.com
 * @date 2021-08-03 16:30:12
 */
@RestController
@RequestMapping("/goods/goods")
@Slf4j
public class GoodsController {
    @Autowired
    private GoodsService goodsService;
    @Value("${fdfs.fastPath}")
    private String fastPath;
    @Autowired
    private GoodsPngService goodsPngService;
    @Autowired
    private StockService stockService;
    // 将fastdfs对象注入进来
    @Autowired
    private FastFileStorageClient fastFileStorageClient;

    // 注入redission的相关对象
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;



    /**
     * 列表
     */
    @RequestMapping("/list")
    public R list(@RequestParam Map<String, Object> params){
        // 1.查询出商品的信息
        PageUtils page = goodsService.queryPage(params);

        // 2.获取当前页的数据(商品信息)
        List<GoodsEntity> list = (List<GoodsEntity>) page.getList();

        // 3.创建一个GoodsVoList,用来存放查询到的所有数据，商品信息，商品图片，商品库存
        List<GoodsAddVo> goodsAddVoList = new ArrayList<>();

        // 4.将商品信息集合信息存入到vo中
        for (GoodsEntity goodsEntity : list) {
            GoodsAddVo goodsAddVo = new GoodsAddVo();
            // 拷贝信息
            BeanUtils.copyProperties(goodsEntity,goodsAddVo);

            // 添加商品图片,根据商品信息的id来查找对应的图片
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("gid",goodsEntity.getId());
            List<GoodsPngEntity> pngList = goodsPngService.list(queryWrapper);
            goodsAddVo.setGoodsPngList(pngList);

            // 添加库存数量
//            StockEntity stockEntity = stockService.getOne(queryWrapper);
//            goodsAddVo.setStock(stockEntity.getStock());

            // 将拷贝后的vo添加到集合中
            goodsAddVoList.add(goodsAddVo);
        }
        // 5.将库存数量放入到vo中

        page.setList(goodsAddVoList);
        return R.ok().put("page", page);
    }

    /**
     * 图片上传
     */
    @RequestMapping("/fileUpLoud")
    public R fileUpLoud(MultipartFile file) throws IOException {
        String extension = FilenameUtils.getExtension(file.getOriginalFilename());

        InputStream is = file.getInputStream();
        long size = file.getSize();

        //将图片存入到fastdfds中
        StorePath storePath = fastFileStorageClient.uploadImageAndCrtThumbImage(is, size, extension, null);

        //获取从fastdfs中传过来的图片地址
        String path = storePath.getPath();
        System.out.println("返回的地址："+path);

        // 添加成功后将图片地址返回给前端
        return R.ok().put("url",fastPath+path);
    }


    /**
     * 信息
     */
    @RequestMapping("/info/{id}")
    public R info(@PathVariable("id") Integer id){
		GoodsEntity goods = goodsService.getById(id);
        return R.ok().put("goods", goods);
    }

    /**
     * 保存
     */
    @RequestMapping("/save")
    public R save(@RequestBody GoodsAddVo goodsAddVo){
        log.debug("goodsVo:{}",goodsAddVo);
		goodsService.addGoods(goodsAddVo);
        return R.ok();
    }

    /**
     * 修改
     */
    @RequestMapping("/update")
    public R update(@RequestBody GoodsEntity goods){
		goodsService.updateById(goods);

        return R.ok();
    }

    /**
     * 删除
     */
    @RequestMapping("/delete")
    public R delete(@RequestBody Integer[] ids){
		goodsService.removeByIds(Arrays.asList(ids));

        return R.ok();
    }

    /**
     * es模块通过openFign访问，调用这个模块的方法得到数据。并将查询所有的数据并存入到es中
     */
    @GetMapping("/getAll")
    public List<GoodsAddVo> getAll(){
//        List<GoodsAddVo> goodsVoList = new ArrayList<>();
//        // 1.查询所有的商品信息
//        List<GoodsEntity> goodsEntityList = goodsService.list();
//        for (GoodsEntity goodsEntity : goodsEntityList) {
//            GoodsAddVo goodsVo = new GoodsAddVo();
//
//            // 拷贝商品的信息到GoodsVO
//            BeanUtils.copyProperties(goodsEntity,goodsVo);
//
//            // 查询商品的图片
//            QueryWrapper queryWrapper = new QueryWrapper();
//            queryWrapper.eq("gid",goodsEntity.getId());
//            List<GoodsPngEntity> list = goodsPngService.list(queryWrapper);
//            goodsVo.setGoodsPngList(list); // 根据商品的id查询商品的图片
//
//            // 库存
//            QueryWrapper queryWrapperStock = new QueryWrapper();
//            queryWrapperStock.eq("gid",goodsEntity.getId());
//            StockEntity stockEntity = stockService.getOne(queryWrapperStock);
//            goodsVo.setStock(stockEntity.getStock());
//
//            // 添加到VO的集合中
//            goodsVoList.add(goodsVo);
//        }
        return goodsService.getGoodsVoList();
    }

    /**
     * 用户点击商品图片，跳转到商品详情页
     * 查询数据库，得到商品的详细信息
     * 因为使用的频率高，所以要加锁
     */
    @GetMapping("/getGoodsVoById/{id}")
    public GoodsVo getGoodsVoById(@PathVariable("id") Integer id){
        return JSON.parseObject(getDBGoodsVo(id),GoodsVo.class);
    }
    private String getDBGoodsVo(Integer id){
        // 1. 查询缓存中是否有数据
        String goodsVoJSON  = stringRedisTemplate.opsForValue().get(ShopGoodsConstants.SHOP_GOODS_VO_PRE + id);
        // 如果黄村中有数据就直接返回缓存中的数据
        if(!StringUtils.isEmpty(goodsVoJSON)){
            return goodsVoJSON;
        }

        // 在缓存中没有查询到数据，就到数据库中查
        // 1.获取锁
        RLock lock = redissonClient.getLock(ShopGoodsConstants.SHOP_GOODS_VO_LOCK_PRE + id);
        // 2.加锁
        boolean b = lock.tryLock();
        // 拿到锁的线程进入，执行业务
        if(b){
            try {
                // 数据库中查询数据
                GoodsVo goodsVo = goodsService.getGoodsVoById(id);
                // 将查询到的数据转化为字符串，存入到redis中并设置7天过期时间
                String goods = JSON.toJSONString(goodsVo);
                stringRedisTemplate.opsForValue().set(ShopGoodsConstants.SHOP_GOODS_VO_PRE+id,goods,7, TimeUnit.DAYS);
                return goods;
            }finally {
                // 3.释放锁
                lock.unlock();
            }
        }else {// 没有拿到锁的线程，休眠后在次查询
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return getDBGoodsVo(id);
        }
    }

}
